SPDX-FileCopyrightText: 2014 Nitay Lehrer SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be
SPDX-License-Identifier: GPL-3.0-or-later
HABITAT 67’ script - Nitay Lehrer - 22/01/2015 Created in blender hash 9337574, OS: Microsoft Windows 7.0
For script to work, PIVOT CENTER needs to be set on “MEDIAN POINT” on both OBJECT and EDIT modes# All PRINT commands are for debugging purposes, and their output is erased before the final output. To enable PRINT outputs, place “#” before os.system(“cls”) , at the very end of the script.
import bpy
import random
import bpy, bmesh
from mathutils import Vector
import osErasing all previously generated objects
bpy.context.scene.layers[0] = False
bpy.context.scene.layers[19] = True
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=False)
bpy.context.scene.layers[0] = True
bpy.context.scene.layers[19] = False
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=False) #---------------------------------------------------------------#
# MAKING THE RANDOM PERIMITER #
#---------------------------------------------------------------#
def myBox(pos_X, pos_Y, pos_Z, dim_X, dim_Y, dim_Z):
bpy.ops.mesh.primitive_cube_add(location=(pos_X, pos_Y, pos_Z))
bpy.ops.transform.resize(value=(0.5, 0.5, 0.5))
bpy.ops.transform.resize(value=(dim_X, dim_Y, dim_Z))
array_X = random.randint(1, 3)
array_Y = random.randint(1, 3)
for j in range(0, array_Y):
for i in range(0, array_X):
scale = random.randint(1, 5)
myBox(i, j, -0.02, random.uniform(0.5, 3), random.uniform(1, 2), 0.01)bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.join() # joining the boxes into one geometry
bpy.context.object.name = "BASE" # Changing the name
bpy.context.object.data.name = "BASE"
bpy.data.objects["BASE"].bound_box
bpy.ops.object.origin_set(
type="ORIGIN_CENTER_OF_MASS"
) # changing the origin of the base plane to the center of mass
bpy.context.object.location[0] = 0 # centering the base plane in the X Y axis
bpy.context.object.location[1] = 0
bpy.context.object.location[2] = -0.01 #--------------------------------------------------------------------#
# DEFINING ALL FUNCTIONS #
#--------------------------------------------------------------------#
CREATING ALL THE LISTS WE WILL USE IN THE SCRIPT:
stack = All the modules used in the process
lastDirection = The last written direction of the module
nextDirection = Once reaching an edge, the next module direction according to the orientation of the edge
elbow = The next elbow to be placed according to the last and next directions
placedElbow = Verification that the last placed elbow is the correct one
cube = The bounding box of the current module
iterationCount = A registry of the amount of times a module has been replicated in a wing
coorObjectMode = Coordinates of the center of the bounding box in object mode, used in edgeAnalysis()
coorEditMode = Coordinates of the center of the bounding box in edit mode, also used in edgeAnalysis()
edgeAnalysisList = A registry of the last orientations of an edge hit by a wing - either "Ver"(tical) or "Hor"(izontal)
stack = []
lastDirection = []
nextDirection = []
elbow = []
placedElbow = []
cube = []
iterationCount = []
coorObjectMode = []
coorEditMode = []
edgeAnalysisList = []THE FUNCTION THAT STARTS THE PROCESS DebName = The predefined name of the start module to look for in layer 1. The name corresponds to the beginning direction. Modname = The predefined name of the first drectional module to look for in layer 2. The name corresponds to the beginning direction. Direction = The Random beginning direction — NW= North-West NE= North-East SE= South-East SW= South-West trans_X = The X manipulation of the module in the chosen direction trans_Y = The Y manipulation of the module in the chosen direction
def START(DebName, ModName, Direction, trans_X, trans_Y): bpy.ops.object.select_all(action="TOGGLE")
bpy.context.scene.layers[1] = True
object = bpy.data.objects[DebName]
object.select = True
bpy.context.scene.objects.active = bpy.data.objects[DebName]
bpy.ops.object.duplicate()
bpy.context.scene.objects.active = bpy.data.objects[DebName + ".001"]Moving the start module into position in layer 0 and turning off layer 1. Changing the name to correspond to the direction.
bpy.ops.object.move_to_layer(
layers=(
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
bpy.context.scene.layers[1] = False
bpy.context.object.name = "Deb" + str(Direction)
bpy.context.object.data.name = "Deb" + str(Direction)
bpy.ops.object.select_all(action="TOGGLE")Moving the first directional module into position in layer 0 and turning off layer 2. Changing the name to correspond to the direction.
bpy.context.scene.layers[2] = True
object2 = bpy.data.objects[ModName]
object2.select = True
bpy.context.scene.objects.active = bpy.data.objects[ModName]
bpy.ops.object.duplicate()
bpy.context.scene.objects.active = bpy.data.objects[ModName + ".001"]
bpy.ops.object.move_to_layer(
layers=(
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
bpy.context.scene.layers[2] = False
bpy.context.object.name = "MOD" + str(Direction)
bpy.context.object.data.name = "MOD" + str(Direction) bpy.context.active_object.location += Vector([trans_X, trans_Y, 0])
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"
stack.append(
bpy.context.scene.objects.active
) # Adding the new module as the first in the list of directional modules ( stack[] )BUILDING THE BOUNDING BOX OF EACH MODULE, THEN INTERSECTING IT WITH THE BASE PLANE. THIS WILL TELL US IF THE MODULE HASE REACHED AN EDGE. According to the direction of the wing and the beginning position of the process, the box will be moved differently. DirectionInt = An integer corresponding to the random initial direction. 0=NW 1=NE 2=SE 3=SW translateBox = The set of vector coordinates that wil govern the displacement of the box, so that it perfectly encompasses the module.
def boxInter2(DirectionInt): if (startingPos == 0 or startingPos == 2) and DirectionInt == 0:
translateBox = (0.02, -0.2264, 0)
elif (startingPos == 1 or startingPos == 3) and DirectionInt == 0:
translateBox = (-0.02, 0.2264, 0)
elif (startingPos == 0 or startingPos == 2) and DirectionInt == 1:
translateBox = (0.02, 0.2264, 0)
elif (startingPos == 1 or startingPos == 3) and DirectionInt == 1:
translateBox = (-0.02, -0.2264, 0)
elif (startingPos == 0 or startingPos == 2) and DirectionInt == 2:
translateBox = (-0.02, 0.2264, 0)
elif (startingPos == 1 or startingPos == 3) and DirectionInt == 2:
translateBox = (0.02, -0.2264, 0)
elif (startingPos == 0 or startingPos == 2) and DirectionInt == 3:
translateBox = (-0.02, -0.2264, 0)
elif (startingPos == 1 or startingPos == 3) and DirectionInt == 3:
translateBox = (0.02, 0.2264, 0) bpy.ops.mesh.primitive_cube_add(
view_align=False,
enter_editmode=False,
location=(0, 0, 0),
)
bpy.ops.transform.resize(value=(0.1265, 0.2265, 0.5))
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_selected_to_cursor(
use_offset=False
) # displacing the center of the box to the cursor
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.transform.translate(
value=translateBox
) # final displacement of the box to fit to module bpy.ops.object.modifier_add(
type="BOOLEAN"
) # Boolean difference operation on base plane
bpy.context.object.modifiers["Boolean"].operation = "DIFFERENCE"
bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["BASE"]
bpy.ops.object.modifier_apply(
apply_as="DATA", modifier="Boolean"
) # applying the boolean to create a hard coded form
bpy.ops.object.modifier_add(
type="DECIMATE"
) # "Decimate" modifier on the remaining geometry
bpy.context.object.modifiers["Decimate"].decimate_type = (
"DISSOLVE" # This merges all coplanar faces, so as not to give false readings in the face count
)
bpy.ops.object.modifier_apply(apply_as="DATA", modifier="Decimate")
result = bpy.context.object
count = len(result.data.polygons) # Counting the amount of faces
edges = len(result.data.edges) # Counting the amount of vertices
cube.append(
bpy.context.scene.objects.active
) # Adding the cube to the list of cubes
print("___1___the number of faces is", str(count))
print("___2___the number of edges is", str(edges))
print("___3___the last cube is", cube[-1])Only a box that is perfectly on top of the base plane will have 12 FACES and 24 VERTICES, anything else means that the box has reached or transgressed an edge.
CREATING A NEW WING OF MODULES
Based on the first directional module, the function copies it until it reaches the edge of the island.
Direction = The required direction of the wing
trans_X = Translation of the copied modules in the X axis
trans_Y = Translation of the modules on the Y axis
DirectionInt = The direction integer fed into the boxInter2() function x = The maximum number of modules in a wing
def wing(Direction, trans_X, trans_Y, DirectionInt):
m = 0
x = 12
while m <= x:
print(
"___4___the last object in stack before wing in iteration",
m + 1,
"is",
stack[-1],
)Analysing the intersected box, left over from boxInter2(), to discover the orientation of the reached edge.
def edgeAnalysisForWing():
A = (
bpy.context.object.location
) # geometric coordinates of the center of the box
bpy.ops.object.editmode_toggle() # going into edit mode, which moves the center of gravity
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected() # moving cursor to new center of the object.
bpy.context.area.type = "TEXT_EDITOR"
B = (
bpy.context.scene.cursor_location
) # retreiving the coordinates of the cursor
bpy.ops.object.editmode_toggle()
coorObjectMode.append(A)
coorEditMode.append(B)
print(A)
print(B)
A = [abs(i) for i in A] # absolute value of coordinates
B = [abs(i) for i in B]
C = [b - a for a, b in zip(A, B)] # Subtracting one vector from the other
C = [abs(i) for i in C]
print(C)
if C[0] > C[1]: # if the result in X is bigger than in Y, the edge is N/S
edgeAnalysisList.append("Ver")
print("___5___the edge is vertical")
else: # if the result is bigger in Y than in X, the edge is E/W
edgeAnalysisList.append("Hor")
print("___5___the edge is horizontal")All necessary action before reiterating Wing() : First, the bounding box is stocked in layer 19, for debugging purposes. Then, the last module is selected again, to be duplicated in the next iteration
def nextIteration():
bpy.ops.object.move_to_layer(
layers=(
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
bpy.context.scene.layers[19] = False
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.select_all(action="TOGGLE")
print("___6___the last object in stack2 is", stack[-1])
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print("___7___the last object is", bpy.context.scene.objects.active) if DirectionInt == 0:
lastDirection.append("NW")
elif DirectionInt == 1:
lastDirection.append("NE")
elif DirectionInt == 2:
lastDirection.append("SE")
elif DirectionInt == 3:
lastDirection.append("SW") bpy.ops.object.duplicate_move(
OBJECT_OT_duplicate={"mode": "TRANSLATION"},
TRANSFORM_OT_translate={"value": (trans_X, trans_Y, 0)},
)
stack.append(
bpy.context.scene.objects.active
) # appending the module to the list
print(
"___8___--THE NEXT OBJECT IN THE WING IS ---",
bpy.context.scene.objects.active,
) bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR" boxInter2(DirectionInt)
print("___9___The bounding box is", bpy.context.scene.objects.active) if (len(bpy.context.object.data.polygons)) != 12 or (
len(bpy.context.object.data.edges)
) != 24:
edgeAnalysisForWing()
x1 = coorObjectMode[-1][
0
] # The x coordinate of the last bounding box in object mode
x2 = coorEditMode[-1][
0
] # The x coordinate of the last bounding box in edit mode
y1 = coorObjectMode[-1][
1
] # The y coordinate of the last bounding box in object mode
y2 = coorEditMode[-1][
1
] # The y coordinate of the last bounding box in object mode
print(
"___10___the coordinates are: x1=", x1, "x2=", x2, "y1=", y1, "y2=", y2
)
if (len(bpy.context.object.data.polygons)) == 6 or (
len(bpy.context.object.data.edges)
) == 12: # the module is totally off the base plane. Stop the wing() function.
iterationCount.append(m)
print(
"\n\t\t\t\t\t after",
m + 1,
"iterations, the operation has reached abbys, the last direction was",
DirectionInt,
"\n",
)
break
elif (
(lastDirection[-1] == "SW" or lastDirection[-1] == "SE")
and (y1 > (y2 + 0.0001))
and edgeAnalysisList[-1] == "Hor"
): # the wing started outside the base plane and wants to go back. It shouldn't be stopped by an edge
print(
"\n\t\t\t\t\t discovered an edge but skipped it, the edge was",
edgeAnalysisList[-1],
"\n",
)
nextIteration()
m = m + 1
elif (
(lastDirection[-1] == "NW" or lastDirection[-1] == "NE")
and (y1 < (y2 - 0.0001))
and edgeAnalysisList[-1] == "Hor"
): # the wing started outside the base plane and wants to go back. It shouldn't be stopped by an edge
print(
"\n\t\t\t\t\t discovered an edge but skipped it, the edge was",
edgeAnalysisList[-1],
"\n",
)
nextIteration()
m = m + 1
elif (
(lastDirection[-1] == "NE" or lastDirection[-1] == "SE")
and (x1 < (x2 + 0.0001))
and edgeAnalysisList[-1] == "Ver"
): # the wing started outside the base plane and wants to go back. It shouldn't be stopped by an edge
print(
"\n\t\t\t\t\t discovered an edge but skipped it, the edge was",
edgeAnalysisList[-1],
"\n",
)
nextIteration()
m = m + 1
elif (
(lastDirection[-1] == "NW" or lastDirection[-1] == "SW")
and (x1 > (x2 - 0.0001))
and edgeAnalysisList[-1] == "Ver"
): # the wing started outside the base plane and wants to go back. It shouldn't be stopped by an edge
print(
"\n\t\t\t\t\t discovered an edge but skipped it, the edge was",
edgeAnalysisList[-1],
"\n",
)
nextIteration()
m = m + 1
else: # The wing has reached an edge from the inside. wing() will be stopped.
iterationCount.append(m)
print(
"\n\t\t\t\t\t after",
m + 1,
"iterations, the operation reached the edge, the last direction was",
DirectionInt,
"\n",
)
break else:
if m == x:
iterationCount.append(m)
print(
"\n\t\t\t\t\t after",
m + 1,
"iterations, the operation reached the abbys, the last direction was",
DirectionInt,
"\n",
)
break
else:
nextIteration()
m = m + 1def moveToLayer19():
bpy.ops.object.move_to_layer(
layers=(
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
True,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
bpy.context.scene.layers[19] = FalseA FURTHER ANALYSIS OF INTERSECTION BETWEEN BOUNDING BOX AND BASE PLANE
This time, it choses which elbow to place after the last wing, according to the last direction, the orientation of the edge, and therefore the next direction
def edgeAnalysis():
A = bpy.context.object.location # geometric coordinates of the center of the box
bpy.ops.object.editmode_toggle() # going into edit mode, which moves the center of gravity
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected() # moving cursor to new center of the object.
bpy.context.area.type = "TEXT_EDITOR"
B = bpy.context.scene.cursor_location # retreiving the coordinates of the cursor
bpy.ops.object.editmode_toggle()
coorObjectMode.append(A)
coorEditMode.append(B)
print(A)
print(B)
A = [abs(i) for i in A] # absolute value of coordinates
B = [abs(i) for i in B]
C = [b - a for a, b in zip(A, B)] # Subtracting one vector from the other
C = [abs(i) for i in C]
print(C)
if C[0] > C[1]: # if the result in X is bigger than in Y, the edge is N/S
print("___9___the edge is vertical")
else: # if the result is bigger in Y than in X, the edge is E/W
print("___9___the edge is horizontal")Erasing modules from the end of the wing to make space for the elbow. The length of the wing determines how many modules will be erased, if at all.
print(
"___10___The box to be MOVED TO LAYER 20 is", bpy.context.scene.objects.active
)
moveToLayer19()
if iterationCount[-1] >= 2:
print("___11___the object to be deleted is", stack[-1])
stack[-1].select = True
bpy.ops.object.delete(use_global=False)
stack.pop() # removing the last module from the list, now we will have a new last module
print("___12___the next object to be deleted is", stack[-1])
stack[-1].select = True
bpy.ops.object.delete(use_global=False)
stack.pop()
print("___13___after deleting, the last object is", stack[-1])
elif iterationCount[-1] == 1:
print("___14___the only object to be deleted is", stack[-1])
stack[-1].select = True
bpy.ops.object.delete(use_global=False)
stack.pop()
else:
print("___15___NO deleting, the last object is STILL", stack[-1])
stack[-1].select = True # selecting the new last module
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"
print("___14___The very last direction is", lastDirection[-1])
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"According to the last know direction and the direction of barrier edge, we can choose our elbow If the module reaches a corner, it is cut in two areas. In this case, the center of mass will move more, paradoxically, towards the side that was cut less(since there is suddenly a dense collection of vertices).Therefore, if the box is cut by a corner (which means that both x and y of the center of mass move), the displacement is transformed by ^-1 so that it reflects the more important edge
If the edge is Horizontal, the direction is flipped horizontally. If vertical, then vertically. Then, the next direction is appended to the list, as well as the chosen elbow
if C[0] > 0.001 and C[1] > 0.001:
print("\n\n*****************the elbow is on a corner**********************\n\n")
if lastDirection[-1] == "NW" and (1 / C[0]) > (1 / C[1]):
nextDirection.append("NE")
elbow.append("NW2NE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NW" and (1 / C[0]) < (1 / C[1]):
nextDirection.append("SW")
elbow.append("NW2SW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NE" and (1 / C[0]) > (1 / C[1]):
nextDirection.append("NW")
elbow.append("NE2NW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NE" and (1 / C[0]) < (1 / C[1]):
nextDirection.append("SE")
elbow.append("NE2SE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SE" and (1 / C[0]) > (1 / C[1]):
nextDirection.append("SW")
elbow.append("SE2SW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SE" and (1 / C[0]) < (1 / C[1]):
nextDirection.append("NE")
elbow.append("SE2NE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SW" and (1 / C[0]) > (1 / C[1]):
nextDirection.append("SE")
elbow.append("SW2SE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SW" and (1 / C[0]) < (1 / C[1]):
nextDirection.append("NW")
elbow.append("SW2NW")
print("___16___the next direction is", nextDirection[-1])
else:
if lastDirection[-1] == "NW" and C[0] > C[1]:
nextDirection.append("NE")
elbow.append("NW2NE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NW" and C[0] < C[1]:
nextDirection.append("SW")
elbow.append("NW2SW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NE" and C[0] > C[1]:
nextDirection.append("NW")
elbow.append("NE2NW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "NE" and C[0] < C[1]:
nextDirection.append("SE")
elbow.append("NE2SE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SE" and C[0] > C[1]:
nextDirection.append("SW")
elbow.append("SE2SW")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SE" and C[0] < C[1]:
nextDirection.append("NE")
elbow.append("SE2NE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SW" and C[0] > C[1]:
nextDirection.append("SE")
elbow.append("SW2SE")
print("___16___the next direction is", nextDirection[-1])
elif lastDirection[-1] == "SW" and C[0] < C[1]:
nextDirection.append("NW")
elbow.append("SW2NW")
print("___16___the next direction is", nextDirection[-1])
print("___17___the elbow is therefore", elbow[-1])FOLLOWING THE CHOICE OF THE ELBOW IN edgeAnalysis(), THE ELBOW IS PLACED AND THE CENTER IS ADJUSTED FOR MIRRORING THE MODULE TO THE OTHER SIDE OF THE ELBOW, READY FOR THE NEXT WING
def elbowChoice(Dir):First, the proper elbow has to be copied from layer 3 or 4. If the last direction is parallel to the beginning direction, the modules will be moving forward and require a module from layer 3. If perpendicular, mirroring will cause modules to move backwards, in which case they will require the elbow from layer 4.
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.select_all(action="TOGGLE")
if Dir == "SW2NW_2" or Dir == "NE2SE_2" or Dir == "NW2SW_2" or Dir == "SE2NE_2":
bpy.context.scene.layers[4] = True
else:
bpy.context.scene.layers[3] = True
bpy.data.objects[Dir].select = True
bpy.context.scene.objects.active = bpy.data.objects[Dir]
print(
"___18___The selected elbow before duplication is", bpy.context.selected_objects
)
bpy.ops.object.duplicate()
placedElbow.append(bpy.context.scene.objects.active)
print(
"___19___The active elbow is",
bpy.context.scene.objects.active,
"the last in the list is",
placedElbow[-1],
)
bpy.ops.object.move_to_layer(
layers=(
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
if Dir == "SW2NW_2" or Dir == "SE2NE_2" or Dir == "NW2SW_2" or Dir == "SE2NE_2":
bpy.context.scene.layers[4] = False
else:
bpy.context.scene.layers[3] = FalseAccording to the chosen elbow, the cursor (and then the origin) has to be displaced differently so that the modules mirror to the same position on the other side.
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
if Dir == "NW2SW" or Dir == "SW2NW":
bpy.context.scene.cursor_location += Vector((-0.10706, 0, 0))
elif Dir == "NE2SE" or Dir == "SE2NE":
bpy.context.scene.cursor_location += Vector((0.10706, 0, 0))
elif Dir == "NW2SW_2" or Dir == "SW2NW_2":
bpy.context.scene.cursor_location += Vector((-0.28859, 0, 0))
elif Dir == "NE2SE_2" or Dir == "SE2NE_2":
bpy.context.scene.cursor_location += Vector((0.28859, 0, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"
scene = bpy.context.scene
for ob in scene.objects:
ob.select = False stack[-1].select = True
print(
"___20___the selected objects after placing elbow is",
bpy.context.selected_objects,
)
bpy.context.scene.objects.active = stack[-1]
print(
"___21___the active object after elbowchoice is",
bpy.context.scene.objects.active,
)NOW THAT THE ELBOW HAS BEEN PREPARED AND THE CURSOR HAS BEEN MOVED TO ITS CENTER, THE NEXT WING CAN BE CREATED.
def nextWing():
print(
"___22___the elbow after executing NEXTWING is", elbow[-1]
) # checking that the lists are behaving like they should
print("___23___the stack after executing NEXTWING is", stack)According to the last elbow and the initial direction, the last module will be mirrored and a new wing will start in the next direction. Modules continuing North or South after bouncing off of a N-S edge will simply be mirrored around their respective extremity. Modules changing from N to S or inversely will be mirrored around their new origin, which is placed in the cursor, which was previously placed in the center of the elbow. The origin is then restored to the habitual place in the new module, by reapplying the same displacement as before.
if (
elbow[-1] == "NW2NE"
): # here, for example, the module is flipped along the x axis, with no exterior elbow.
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"______24_______The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_______The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
if startingPos == 1 or startingPos == 3:
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, 0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, 0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
else:
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
stack.append(bpy.context.scene.objects.active)
wing("NE", 0.16, 0.16, 1)
elif (
elbow[-1] == "NW2SW"
): # here it is flipped along the Y axis, so an elbow is added.
if startingPos == 0 or startingPos == 2:
elbowChoice("NW2SW")
else:
elbowChoice("NW2SW_2")
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"_____24______The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"_____25______The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(True, False, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
if startingPos == 0 or startingPos == 2:
bpy.context.scene.cursor_location += Vector((-0.10706, 0, 0))
else:
bpy.context.scene.cursor_location += Vector((-0.28859, 0, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
stack.append(bpy.context.scene.objects.active)
stack[-2].select = False
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
wing("SW", -0.16, -0.16, 3)
elif elbow[-1] == "NE2NW":
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"_____24______The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"_____25______The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
if startingPos == 0 or startingPos == 2:
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, 0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, 0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
else:
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
print(
"___24___the first active object in next wing is",
bpy.context.scene.objects.active,
)
stack.append(bpy.context.scene.objects.active)
wing("NW", -0.16, 0.16, 0)
elif elbow[-1] == "NE2SE":
if startingPos == 1 or startingPos == 3:
elbowChoice("NE2SE")
else:
elbowChoice("NE2SE_2")
bpy.ops.object.select_all(action="TOGGLE")
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"______24_____The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_____The SELECTED objects AFTER duplicating are_____________",
bpy.context.selected_objects,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(True, False, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
if startingPos == 0 or startingPos == 2:
bpy.context.scene.cursor_location += Vector((0.28859, 0, 0))
else:
bpy.context.scene.cursor_location += Vector((0.10706, 0, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
stack.append(bpy.context.scene.objects.active)
stack[-2].select = False
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
wing("SE", 0.16, -0.16, 2)
elif elbow[-1] == "SE2SW":
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"______24_____The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_____The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
if startingPos == 0 or startingPos == 2:
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
else:
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, -0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, -0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
print(
"___24___the first active object in next wing is",
bpy.context.scene.objects.active,
)
stack.append(bpy.context.scene.objects.active)
wing("SW", -0.16, -0.16, 3)
elif elbow[-1] == "SE2NE":
if startingPos == 0 or startingPos == 2:
elbowChoice("SE2NE")
else:
elbowChoice("SE2NE_2")
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"______24_____The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_____The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(True, False, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
print(
"___26___the CURSOR position BEFORE moving it is",
bpy.context.scene.cursor_location,
)
bpy.context.area.type = "VIEW_3D"
if startingPos == 0 or startingPos == 2:
bpy.context.scene.cursor_location += Vector((0.10706, 0, 0))
else:
bpy.context.scene.cursor_location += Vector((0.28859, 0, 0))
bpy.context.area.type = "TEXT_EDITOR"
print(
"___27___the CURSOR position AFTER moving it is",
bpy.context.scene.cursor_location,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
stack.append(bpy.context.scene.objects.active)
stack[-2].select = False
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
wing("NE", 0.16, 0.16, 1)
elif elbow[-1] == "SW2SE":
bpy.context.scene.objects.active = stack[-1]
print(
"______24_____The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_____The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
if startingPos == 0 or startingPos == 2:
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, -0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
bpy.context.scene.cursor_location += Vector((0, -0.453, 0))
bpy.context.area.type = "TEXT_EDITOR"
else:
bpy.ops.transform.mirror(
constraint_axis=(False, True, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
print(
"___24___the first active object in next wing is",
bpy.context.scene.objects.active,
)
stack.append(bpy.context.scene.objects.active)
wing("SE", 0.16, -0.16, 2)
elif elbow[-1] == "SW2NW":
if startingPos == 1 or startingPos == 3:
elbowChoice("SW2NW")
else:
elbowChoice("SW2NW_2")
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
print(
"______24_____The active object BEFORE duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.duplicate()
print(
"______25_____The active object AFTER duplicating is_____________",
bpy.context.scene.objects.active,
)
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.transform.mirror(
constraint_axis=(True, False, False),
constraint_orientation="GLOBAL",
proportional="DISABLED",
proportional_edit_falloff="SMOOTH",
proportional_size=1,
)
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
if startingPos == 0 or startingPos == 2:
bpy.context.scene.cursor_location += Vector((-0.28859, 0, 0))
else:
bpy.context.scene.cursor_location += Vector((-0.10706, 0, 0))
bpy.context.area.type = "TEXT_EDITOR"
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
stack.append(bpy.context.scene.objects.active)
stack[-2].select = False
stack[-1].select = True
bpy.context.scene.objects.active = stack[-1]
wing("NW", -0.16, 0.16, 0)AFTER THE FINAL WING, THE END PIECE, IDENTICAL TO THE START PIECE, MUST BE ORIENTATED AND PLACED. THIS IS DONE ACCORDING TO THE DIRECTION OF THE LAST MODULE AND ITS TRAVEL ORIENTATION.
def end():
endPiece = []
if nextDirection[-1] == "NW":
if nextDirection[0] in ("NW", "SE"):
endName = "endNW"
else:
endName = "endSE"
elif nextDirection[-1] == "NE":
if nextDirection[0] in ("NE", "SW"):
endName = "endNE"
else:
endName = "endSE"
elif nextDirection[-1] == "SW":
if nextDirection[0] in ("SW", "NE"):
endName = "endSW"
else:
endName = "endNE"
elif nextDirection[-1] == "SE":
if nextDirection[0] in ("SE", "NW"):
endName = "endSE"
else:
endName = "endNW"
scene = bpy.context.scene
bpy.ops.object.select_all(action="TOGGLE")
bpy.context.scene.layers[5] = True
object = bpy.data.objects[endName]
object.select = True
bpy.context.scene.objects.active = bpy.data.objects[endName]
bpy.ops.object.duplicate()
endPiece.append(bpy.context.scene.objects.active)
print("_____THE ENDPIECE IS_____", endPiece[-1])
bpy.ops.object.move_to_layer(
layers=(
True,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
False,
)
)
l = [False] * 20
l[0] = True
bpy.context.scene.layers = l
bpy.context.scene.layers[5] = False
bpy.context.scene.layers[0] = True
for ob in scene.objects:
ob.select = False
stack[-1].select = True
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_cursor_to_selected()
bpy.context.area.type = "TEXT_EDITOR"
for ob in scene.objects:
ob.select = False
endPiece[-1].select = True
bpy.context.area.type = "VIEW_3D"
bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
bpy.context.area.type = "TEXT_EDITOR"THE SEQUENCE IS STARTED WITH A RANDOM INTEGER, FROM 0 TO 3, DENOTING THE STARTING DIRECTION
startingPos = random.randint(0, 3) # a random initial direction
print(
"\n\n\n\n\n\n start \n\n\n\n\n\n"
) # This is printed to seperate from previous outputs while debugging
if startingPos == 0:
nextDirection.append("NW")
print("the starting direction is", "NW")
elif startingPos == 1:
nextDirection.append("NE")
print("the starting direction is", "NE")
elif startingPos == 2:
nextDirection.append("SE")
print("the starting direction is", "SE")
elif startingPos == 3:
nextDirection.append("SW")
print("the starting direction is", "SW")
z = 8 # This counts the number of wings in the sequence
if startingPos == 0:
START(
"DEB1", "MOD1", "NW", -0.16, 0.16
) # places the starting module and the first directional module
wing("NW", -0.16, 0.16, 0) # builds the first wing in the randomly chosen direction
x = 0
while x < z:
edgeAnalysis() # analyses the edge when the first wing stops
nextWing() # builds the next wing
x = x + 1
moveToLayer19() # after all wings are done, the last remaining bounding box is moved to layer 19
elif startingPos == 1:
START("DEB2", "MOD2", "NE", 0.16, 0.16)
wing("NE", 0.16, 0.16, 1)
x = 0
while x < z:
edgeAnalysis()
nextWing()
x = x + 1
moveToLayer19()
elif startingPos == 2:
START("DEB3", "MOD3", "SE", 0.16, -0.16)
wing("SE", 0.16, -0.16, 2)
x = 0
while x < z:
edgeAnalysis()
nextWing()
x = x + 1
moveToLayer19()
elif startingPos == 3:
START("DEB4", "MOD4", "SW", -0.16, -0.16)
wing("SW", -0.16, -0.16, 3)
x = 0
while x < z:
edgeAnalysis()
nextWing()
x = x + 1
moveToLayer19()Finally, some modules are removed, according to the length of the last wing, so as to make place for the end module Then, the end moduled is position in place.
x = iterationCount[-1] + 1
if x < 4:
y = 2
else:
y = 3
while y > 0:
stack[-1].select = True
bpy.ops.object.delete(use_global=False)
stack.pop()
y = y - 1
end()
os.system(
"cls"
) # This clears all output from the system console. To disable, place hash tag in the beginning of this line.
a = len(stack) + 1
b = z
c = nextDirection[0]
d = nextDirection[-1]
print("\n\n\n")
print(
" ########################################################################################################################"
)
print(
" # #"
)
print(
" HABITAT 67' - BOUND DEVELOPMENT "
)
print(
" # #"
)
print(
" This conjugation of the Habitat 67' vocabulary has",
a,
"modules, in",
b,
"wings ",
)
print(
" # #"
)
print(
" The first direction was",
c,
"and the last direction was",
d,
" ",
)
print(
" # #"
)
print(
" ########################################################################################################################"
)